#include "vsf.h"
#include "component/port/linux/vsflinux.h"

#include <fcntl.h>
#include <unistd.h>

#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/un.h>

uint32_t htonl(uint32_t hostlong)
{
	return SYS_TO_BE_U32(hostlong);
}

uint16_t htons(uint16_t hostshort)
{
	return SYS_TO_BE_U16(hostshort);
}

uint32_t ntohl(uint32_t netlong)
{
	return BE_TO_SYS_U32(netlong);
}

uint16_t ntohs(uint16_t netshort)
{
	return BE_TO_SYS_U16(netshort);
}

struct vsflinux_sock_priv_t
{
	int domain;
	int type;
	int protocol;
	const struct vsflinux_sock_op_t *sockop;

	unsigned listening : 1;
	unsigned toclose : 1;

	union
	{
		struct
		{
			int backlog;
		};
		struct
		{
			int listener_fd;
		};
	};
};

struct vsflinux_sock_op_t
{
	int priv_size;
	int (*init)(struct vsflinux_sock_priv_t *priv);

	int (*connect)(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
	int (*listen)(int sockfd, int backlog);
	int (*accept)(int sockfd, struct sockaddr *addr, socklen_t *addr_len);
	int (*bind)(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
	int (*getsockopt)(int sockfd, int level, int optname, void *optval, socklen_t *optlen);
	int (*setsockopt)(int sockfd, int level, int optname,const void *optval, socklen_t optlen);

	struct vsflinux_fdop_t fdop;
};

#ifdef VSFLINUX_CFG_AF_UNIX_EN
// socket unix
struct vsflinux_sock_unix_priv_t
{
	struct vsflinux_sock_priv_t common;
	int remote_fd;
	struct vsf_buffer_t rxbuf;
};

int vsflinux_sock_unix_init(struct vsflinux_sock_priv_t *priv)
{
	((struct vsflinux_sock_unix_priv_t *)priv)->remote_fd = -1;
	return 0;
}

static int vsflinux_sock_unix_fcntl(struct vsflinux_fd_t *sfd, int cmd, long arg)
{
	switch (cmd)
	{
	case F_GETFL: return sfd->flags;
	case F_SETFL:
	{
		int diff = arg ^ sfd->flags;
		if (diff & O_NONBLOCK)
		{
			
		}
		sfd->flags = arg;
		return 0;
	}
	default: return -1;
	}
}

static ssize_t vsflinux_sock_unix_read(struct vsflinux_fd_t *sfd, void *buf, size_t count)
{
	struct vsflinux_sock_unix_priv_t *priv = (struct vsflinux_sock_unix_priv_t *)sfd->priv;

	if (priv->common.toclose)
		return -1;

	switch (priv->common.domain)
	{
	case AF_UNIX:
	{
		ssize_t readsize = 0, cursize;

		if (priv->remote_fd < 0)
			return -1;
		if (!(sfd->flags & O_NONBLOCK) && !priv->rxbuf.size)
		{
			vsflinux_fd_tx_pend(sfd);
			if (priv->remote_fd < 0)
				return -1;
		}

		if (priv->rxbuf.size && count)
		{
			cursize = priv->rxbuf.size;
			cursize = min(cursize, count);
			memcpy(buf, priv->rxbuf.buffer, cursize);

			count -= cursize;
			readsize += cursize;
			buf = (uint8_t *)buf + cursize;
			priv->rxbuf.size -= cursize;
			if (priv->rxbuf.size > 0)
				priv->rxbuf.buffer += cursize;
			else
			{
				struct vsflinux_fd_t *rsfd = vsflinux_fd_get(priv->remote_fd);
				sfd->rxevt = false;
				vsflinux_fd_tx_sendevt(rsfd);
			}
		}
		return readsize;
	}
	default: return -1;
	}
}

static ssize_t vsflinux_sock_unix_write(struct vsflinux_fd_t *sfd, const void *buf, size_t count)
{
	struct vsflinux_sock_unix_priv_t *priv = (struct vsflinux_sock_unix_priv_t *)sfd->priv;
	uint8_t *buf8 = (uint8_t *)buf;

	if (priv->common.toclose)
		return -1;

	switch (priv->common.domain)
	{
	case AF_UNIX:
	{
		ssize_t writesize = 0;
		if (priv->remote_fd < 0)
			return -1;

		struct vsflinux_fd_t *rsfd = vsflinux_fd_get(priv->remote_fd);
		struct vsflinux_sock_unix_priv_t *rpriv = (struct vsflinux_sock_unix_priv_t *)rsfd->priv;

		while (rpriv->rxbuf.size)
		{
			vsflinux_fd_tx_pend(sfd);
			if (priv->remote_fd < 0)
				return -1;
			continue;
		}

		rpriv->rxbuf.buffer = buf8;
		rpriv->rxbuf.size = count;
		sfd->txevt = false;
		writesize += count;
		if (writesize)
			vsflinux_fd_rx_sendevt(rsfd);

		while (rpriv->rxbuf.size)
		{
			vsflinux_fd_tx_pend(sfd);
			if (priv->remote_fd < 0)
				return -1;
			continue;
		}
		sfd->txevt = true;
		return writesize;
	}
	default: return -1;
	}
}

static int vsflinux_sock_unix_close(struct vsflinux_fd_t *sfd)
{
	struct vsflinux_sock_unix_priv_t *priv = (struct vsflinux_sock_unix_priv_t *)sfd->priv;

	switch (priv->common.domain)
	{
	case AF_UNIX:
	{
		struct vsflinux_fd_t *rsfd;
		struct vsflinux_sock_unix_priv_t *rpriv;

		if (priv->remote_fd >= 0)
		{
			if (!priv->common.listening)
			{
				rsfd = vsflinux_fd_get(priv->common.listener_fd);
				rpriv = (struct vsflinux_sock_unix_priv_t *)rsfd->priv;
				rpriv->common.backlog++;
			}
			else
			{
				vsflist_foreach(__sfd, sfd->list.next, struct vsflinux_fd_t, list,
				{
					rpriv = (struct vsflinux_sock_unix_priv_t *)__sfd->priv;
					rpriv->common.toclose = true;
				});
			}

			rsfd = vsflinux_fd_get(priv->remote_fd);
			rpriv = (struct vsflinux_sock_unix_priv_t *)rsfd->priv;
			rpriv->remote_fd = -1;

			if (rsfd != NULL)
				vsflinux_fd_rx_sendevt(rsfd);

			rsfd = vsflinux_fd_get(priv->remote_fd);
			if (rsfd != NULL)
				vsflinux_fd_tx_sendevt(rsfd);
		}
		return 0;
	}
	default: return -1;
	}
}

static int vsflinux_sock_unix_connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
{
	struct vsflinux_fd_t *sfd = vsflinux_fd_get(sockfd);
	struct vsflinux_sock_unix_priv_t *priv = (struct vsflinux_sock_unix_priv_t *)sfd->priv;

	switch (priv->common.domain)
	{
	case AF_UNIX:
	{
		struct sockaddr_un *addrun = (struct sockaddr_un *)addr;
		int fd = open(addrun->sun_path, 0);
		if (fd < 0) return -1;

		struct vsflinux_fd_t *fsfd = vsflinux_fd_get(fd);
		if (fsfd->op != &vsflinux_vsfile_fdop)
		{
			close(fd);
			return -1;
		}

		struct vsflinux_vsfile_priv_t *fpriv = (struct vsflinux_vsfile_priv_t *)fsfd->priv;
		struct vsfile_t *file = fpriv->file;
		if (file->op != &vsfile_vfs_op)
		{
			close(fd);
			return -1;
		}

		struct vsfile_vfsfile_t *vfsfile = (struct vsfile_vfsfile_t *)file;
		if ((vfsfile->file.attr & VSFILE_ATTR_DIRECTORY) ||
			!vfsfile->f.priv)
		{
			close(fd);
			return -1;
		}

		priv->remote_fd = (int)vfsfile->f.priv;
		close(fd);

		struct vsflinux_fd_t *rsfd = vsflinux_fd_get(priv->remote_fd);
		struct vsflinux_sock_unix_priv_t *rpriv = (struct vsflinux_sock_unix_priv_t *)rsfd->priv;
		if ((rsfd->op != &vsflinux_sock_fdop) || !rpriv->common.listening ||
			!rpriv->common.backlog)
		{
			priv->remote_fd = -1;
			return -1;
		}

		rpriv->remote_fd = sockfd;
		vsflinux_fd_rx_sendevt(rsfd);
		vsflinux_fd_rx_pend(sfd);
		if (priv->remote_fd < 0)
			return -1;
		sfd->txevt = true;
		return 0;
	}
	default: return -1;
	}
}

static int vsflinux_sock_unix_listen(int sockfd, int backlog)
{
	struct vsflinux_fd_t *lsfd = vsflinux_fd_get(sockfd);
	struct vsflinux_sock_unix_priv_t *lpriv = (struct vsflinux_sock_unix_priv_t *)lsfd->priv;

	if (lpriv->common.listening)
		return -1;

	switch (lpriv->common.domain)
	{
	case AF_UNIX:
		if (lpriv->remote_fd >= 0)
			return -1;
		lpriv->common.listening = true;
		lpriv->common.backlog = backlog;
		return 0;
	default: return -1;
	}
}

static int vsflinux_sock_unix_accept(int sockfd, struct sockaddr *addr, socklen_t *addr_len)
{
	struct vsflinux_fd_t *lsfd = vsflinux_fd_get(sockfd);
	struct vsflinux_sock_unix_priv_t *lpriv = (struct vsflinux_sock_unix_priv_t *)lsfd->priv;
	int new_fd = -1;

	if (lpriv->common.listening && lpriv->common.backlog)
	{
		switch (lpriv->common.domain)
		{
		case AF_UNIX:
			vsflinux_fd_rx_pend(lsfd);
			new_fd = socket(lpriv->common.domain, lpriv->common.type, lpriv->common.protocol);
			if (new_fd >= 0)
			{
				struct vsflinux_fd_t *new_sfd = vsflinux_fd_get(new_fd), *rsfd;
				struct vsflinux_sock_priv_t *new_priv = (struct vsflinux_sock_priv_t *)new_sfd->priv, *rpriv;

				new_priv->remote_fd = lpriv->unix.remote_fd;
				new_priv->listener_fd = sockfd;
				new_sfd->list.next = lsfd->list.next;
				lsfd->list.next = &new_sfd->list;
				lpriv->remote_fd = -1;
				lpriv->common.backlog--;

				rsfd = vsflinux_fd_get(new_priv->remote_fd);
				rsfd->list.next = lsfd->list.next;
				lsfd->list.next = &rsfd->list;
				rpriv = (struct vsflinux_sock_priv_t *)rsfd->priv;
				rpriv->remote_fd = new_fd;
				rpriv->listener_fd = sockfd;

				vsflinux_fd_rx_sendevt(rsfd);
				new_sfd->txevt = true;
			}
			return new_fd;
		default: return -1;
		}
	}
	return new_fd;
}

static int vsflinux_sock_unix_bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
{
	switch (addr->sa_family)
	{
	case AF_UNIX:
	{
		struct sockaddr_un *addrun = (struct sockaddr_un *)addr;
		int fd = open(addrun->sun_path, O_CREAT, 0777);
		if (fd < 0) return -1;

		struct vsflinux_fd_t *sfd = vsflinux_fd_get(fd);
		if (sfd->op != &vsflinux_vsfile_fdop)
		{
			close(fd);
			return -1;
		}

		struct vsflinux_vsfile_priv_t *priv = (struct vsflinux_vsfile_priv_t *)sfd->priv;
		struct vsfile_t *file = priv->file;
		if (file->op != &vsfile_vfs_op)
		{
			close(fd);
			return -1;
		}

		struct vsfile_vfsfile_t *vfsfile = (struct vsfile_vfsfile_t *)file;
		if ((vfsfile->file.attr & VSFILE_ATTR_DIRECTORY) ||
			(vfsfile->f.priv != NULL))
		{
			close(fd);
			return -1;
		}

		vfsfile->f.priv = (void *)sockfd;
		return 0;
	}
	default: return -1;
	}
}

static const struct vsflinux_sock_op_t vsflinux_sock_unix_op =
{
	.priv_size = sizeof(struct vsflinux_sock_unix_priv_t),
	.init = vsflinux_sock_unix_init,
	.connect = vsflinux_sock_unix_connect,
	.listen = vsflinux_sock_unix_listen,
	.accept = vsflinux_sock_unix_accept,
	.bind = vsflinux_sock_unix_bind,

	.fdop =
	{
		.fcntl = vsflinux_sock_unix_fcntl,
		.read = vsflinux_sock_unix_read,
		.write = vsflinux_sock_unix_write,
		.close = vsflinux_sock_unix_close,
	},
};
#endif

#ifdef VSFLINUX_CFG_AF_INET_EN
// socket inet
struct vsflinux_sock_inet_priv_t
{
	struct vsflinux_sock_priv_t common;
	struct vsfip_socket_t *vsfsock;
	struct vsfip_buffer_t *sockbuf;
};

int vsflinux_sock_inet_init(struct vsflinux_sock_priv_t *priv)
{
	struct vsflinux_sock_inet_priv_t *in_priv = (struct vsflinux_sock_inet_priv_t *)priv;
	in_priv->vsfsock = vsfip_socket((enum vsfip_sockfamilt_t)in_priv->common.domain,
							(enum vsfip_sockproto_t)in_priv->common.protocol);
	return !in_priv->vsfsock ? -1 : 0;
}

static int vsflinux_sock_inet_fcntl(struct vsflinux_fd_t *sfd, int cmd, long arg)
{
	switch (cmd)
	{
	case F_GETFL: return sfd->flags;
	case F_SETFL:
	{
		int diff = arg ^ sfd->flags;
		if (diff & O_NONBLOCK)
		{
			
		}
		sfd->flags = arg;
		return 0;
	}
	default: return -1;
	}
}

static ssize_t vsflinux_sock_inet_read(struct vsflinux_fd_t *sfd, void *buf, size_t count)
{
	struct vsflinux_sock_inet_priv_t *priv = (struct vsflinux_sock_inet_priv_t *)sfd->priv;

	if (priv->common.toclose)
		return -1;

	switch (priv->common.domain)
	{
	case AF_INET:
	{
		struct vsfip_buffer_t *sockbuf = priv->sockbuf;
		size_t realsize = 0;

		if (!sockbuf)
		{
			struct vsfip_socket_t *vsfsock = priv->vsfsock;
			struct vsfsm_pt_t pt =
			{
				.sm = &(vsfsm_thread_get_cur())->sm,
				.state = 0,
			};
			vsfsm_evt_t evt = VSFSM_EVT_NONE;
			vsf_err_t err;

			do {
				switch (priv->common.protocol)
				{
				case IPPROTO_TCP:
					err = vsfip_tcp_recv(&pt, evt, vsfsock, &sockbuf);
					break;
				default:
					err = VSFERR_FAIL;
					break;
				}
				if (err <= 0) break;
				else evt = vsfsm_thread_wait();
			} while (1);
			if (!err) priv->sockbuf = sockbuf;
			else return -1;
		}

		sockbuf = priv->sockbuf;
		if (sockbuf != NULL)
		{
			realsize = min(count, sockbuf->app.size);
			memcpy(buf, sockbuf->app.buffer, realsize);
			sockbuf->app.buffer += realsize;
			sockbuf->app.size -= realsize;
			if (!sockbuf->app.size)
			{
				vsfip_buffer_release(sockbuf);
				priv->sockbuf = NULL;
			}
		}
		return realsize;
	}
	default: return -1;
	}
}

static ssize_t vsflinux_sock_inet_write(struct vsflinux_fd_t *sfd, const void *buf, size_t count)
{
	struct vsflinux_sock_inet_priv_t *priv = (struct vsflinux_sock_inet_priv_t *)sfd->priv;
	uint8_t *buf8 = (uint8_t *)buf;

	if (priv->common.toclose)
		return -1;

	switch (priv->common.domain)
	{
	case AF_INET:
	{
		struct vsfip_socket_t *vsfsock = priv->vsfsock;
		struct vsfip_buffer_t *sockbuf;
		size_t realsize = 0, cursize = 0;
		struct vsfsm_pt_t pt =
		{
			.sm = &(vsfsm_thread_get_cur())->sm,
		};
		vsfsm_evt_t evt = VSFSM_EVT_NONE;
		vsf_err_t err;

		while (count)
		{
			switch (priv->common.protocol)
			{
			case IPPROTO_TCP:
				cursize = min(count, VSFIP_CFG_TCP_MSS);
				sockbuf = VSFIP_TCPBUF_GET(cursize);
				if (!sockbuf) return realsize;
				memcpy(sockbuf->app.buffer, buf8, cursize);

				pt.state = 0;
				while (1)
				{
					err = vsfip_tcp_send(&pt, evt, vsfsock, sockbuf, false);
					if (err <= 0) break;
					else evt = vsfsm_thread_wait();
				}
				if (err < 0)
				{
					vsfip_buffer_release(sockbuf);
					return realsize;
				}
				buf8 += cursize;
				count -= cursize;
				realsize += cursize;
				break;
			default:
				err = VSFERR_FAIL;
				break;
			}
		}
		return realsize;
	}
	default: return -1;
	}
}

static int vsflinux_sock_inet_close(struct vsflinux_fd_t *sfd)
{
	struct vsflinux_sock_inet_priv_t *priv = (struct vsflinux_sock_inet_priv_t *)sfd->priv;

	switch (priv->common.domain)
	{
	case AF_INET:
		if (priv->vsfsock != NULL)
		{
			switch (priv->common.protocol)
			{
			case IPPROTO_TCP:
			{
				struct vsfsm_pt_t pt =
				{
					.sm = &(vsfsm_thread_get_cur())->sm,
					.state = 0,
				};
				vsfsm_evt_t evt = VSFSM_EVT_NONE;
				vsf_err_t err;

				while (1)
				{
					err = vsfip_tcp_close(&pt, evt, priv->vsfsock);
					if (err <= 0) break;
					else evt = vsfsm_thread_wait();
				}
				break;
			}
			}
			vsfip_close(priv->vsfsock);
			priv->vsfsock = NULL;
			return 0;
		}
	default:
		return -1;
		break;
	}
}

static int vsflinux_sock_inet_connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
{
	struct vsflinux_fd_t *sfd = vsflinux_fd_get(sockfd);
	struct vsflinux_sock_inet_priv_t *priv = (struct vsflinux_sock_inet_priv_t *)sfd->priv;

	switch (priv->common.domain)
	{
	case AF_INET:
	{
		struct sockaddr_in *addrin = (struct sockaddr_in *)addr;
		struct vsfip_sockaddr_t sockaddr =
		{
			.sin_port = addrin->sin_port,
			.sin_addr.size = 4,
			.sin_addr.addr.s_addr = addrin->sin_addr.s_addr,
		};
		struct vsfsm_pt_t pt =
		{
			.sm = &(vsfsm_thread_get_cur())->sm,
			.state = 0,
		};
		vsfsm_evt_t evt = VSFSM_EVT_NONE;
		vsf_err_t err;

		do {
			err = vsfip_tcp_connect(&pt, evt, priv->vsfsock, &sockaddr);
			if (err <= 0) break;
			else evt = vsfsm_thread_wait();
		} while (1);
		return err ? -1 : 0;
	}
	default: return -1;
	}
}

static int vsflinux_sock_inet_listen(int sockfd, int backlog)
{
	struct vsflinux_fd_t *lsfd = vsflinux_fd_get(sockfd);
	struct vsflinux_sock_inet_priv_t *lpriv = (struct vsflinux_sock_inet_priv_t *)lsfd->priv;

	if (lpriv->common.listening)
		return -1;

	switch (lpriv->common.domain)
	{
	case AF_INET:
		return -1;
	default: return -1;
	}
}

static int vsflinux_sock_inet_accept(int sockfd, struct sockaddr *addr, socklen_t *addr_len)
{
	struct vsflinux_fd_t *lsfd = vsflinux_fd_get(sockfd);
	struct vsflinux_sock_inet_priv_t *lpriv = (struct vsflinux_sock_inet_priv_t *)lsfd->priv;
	int new_fd = -1;

	if (lpriv->common.listening && lpriv->common.backlog)
	{
		switch (lpriv->common.domain)
		{
		case AF_INET:
			return new_fd;
		default: return -1;
		}
	}
	return new_fd;
}

static int vsflinux_sock_inet_bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
{
	switch (addr->sa_family)
	{
	case AF_INET:
	{
		return -1;
	}
	default: return -1;
	}
}


static const struct vsflinux_sock_op_t vsflinux_sock_inet_op =
{
	.priv_size = sizeof(struct vsflinux_sock_inet_priv_t),
	.init = vsflinux_sock_inet_init,
	.connect = vsflinux_sock_inet_connect,
	.listen = vsflinux_sock_inet_listen,
	.accept = vsflinux_sock_inet_accept,
	.bind = vsflinux_sock_inet_bind,

	.fdop =
	{
		.fcntl = vsflinux_sock_inet_fcntl,
		.read = vsflinux_sock_inet_read,
		.write = vsflinux_sock_inet_write,
		.close = vsflinux_sock_inet_close,
	},
};
#endif

int socket(int domain, int type, int protocol)
{
	const struct vsflinux_sock_op_t *sockop = NULL;
	struct vsflinux_sock_priv_t *priv;
	struct vsflinux_fd_t *sfd;
	int fd;

	switch (domain)
	{
#ifdef VSFLINUX_CFG_AF_UNIX_EN
	case AF_UNIX:
		sockop = &vsflinux_sock_unix_op; break;
#endif
#ifdef VSFLINUX_CFG_AF_INET_EN
	case AF_INET:
		sockop = &vsflinux_sock_inet_op; break;
#endif
	default: return -1;
	}

	fd = vsflinux_fd_new(&sfd, sockop->priv_size, &sockop->fdop);
	if (fd >= 0)
	{
		priv = (struct vsflinux_sock_priv_t *)sfd->priv;
		priv->sockop = sockop;
		priv->domain = domain;
		priv->type = type;
		priv->protocol = protocol;

		if (sockop->init(priv))
		{
			vsflinux_fd_del(sfd);
			return -1;
		}
	}
	return fd;
}

int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
{
	struct vsflinux_fd_t *lsfd = vsflinux_fd_get(sockfd);
	struct vsflinux_sock_priv_t *lpriv = (struct vsflinux_sock_priv_t *)lsfd->priv;

	if (!lsfd || lpriv->listening)
		return -1;

	return lpriv->sockop->connect(sockfd, addr, addrlen);
}

int listen(int sockfd, int backlog)
{
	struct vsflinux_fd_t *lsfd = vsflinux_fd_get(sockfd);
	struct vsflinux_sock_priv_t *lpriv = (struct vsflinux_sock_priv_t *)lsfd->priv;

	if (!lsfd || lpriv->listening)
		return -1;

	return lpriv->sockop->listen(sockfd, backlog);
}

int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
{
	struct vsflinux_fd_t *sfd = vsflinux_fd_get(sockfd);
	struct vsflinux_sock_priv_t *priv = (struct vsflinux_sock_priv_t *)sfd->priv;

	if (!sfd) return -1;

	return priv->sockop->accept(sockfd, addr, addrlen);
}

int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
{
	struct vsflinux_fd_t *sfd = vsflinux_fd_get(sockfd);
	struct vsflinux_sock_priv_t *priv = (struct vsflinux_sock_priv_t *)sfd->priv;

	if (!sfd) return -1;

	return priv->sockop->bind(sockfd, addr, addrlen);
}

int getsockopt(int sockfd, int level, int optname, void *optval, socklen_t *optlen)
{
	struct vsflinux_fd_t *sfd = vsflinux_fd_get(sockfd);
	struct vsflinux_sock_priv_t *priv = (struct vsflinux_sock_priv_t *)sfd->priv;

	if (!sfd) return -1;

	switch (optname)
	{
	case SO_TYPE:
		if (optval != NULL) *(int *)optval = priv->type;
		if (optlen != NULL) *optlen = sizeof(priv->type);
		break;
	case SO_ERROR:
		if (optval != NULL) *(int *)optval = 0;
		if (optlen != NULL) *optlen = sizeof(int);
		break;
	default: return -1;
	}
	return 0;
}

int setsockopt(int sockfd, int level, int optname,const void *optval, socklen_t optlen)
{
	struct vsflinux_fd_t *sfd = vsflinux_fd_get(sockfd);
//	struct vsflinux_sock_priv_t *priv = (struct vsflinux_sock_priv_t *)sfd->priv;

	if (!sfd) return -1;
	return 0;
}

int send(int sockfd, const void *buf, size_t len, int flags)
{
	return write(sockfd, buf, len);
}

int recv(int sockfd, void *buf, size_t len, int flags)
{
	return read(sockfd, buf, len);
}

int shutdown(int sockfd, int how)
{
	return close(sockfd);
}

